﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using System.Data;
using System.Web.Script.Serialization;
using System.Reflection;

namespace Service.ZSJL.Com.Utils
{
    public static class JSON
    {
        public static string DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss";
        /// <summary>
        /// 序列化成json字符串
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        public static string ToJsonString(this object o)
        {
            if (o == null || o.ToString() == "null") return null;

            if (o != null && (o.GetType() == typeof(String) || o.GetType() == typeof(string)))
            {
                return o.ToString();
            }
            IsoDateTimeConverter dt = new IsoDateTimeConverter();
            dt.DateTimeFormat = DateTimeFormat;
            return JsonConvert.SerializeObject(o, dt);
        }

        /// <summary>
        /// 把json字符串反序列化成对象
        /// </summary>
        /// <typeparam name="T">需要反序列化的对象类型</typeparam>
        /// <param name="json"></param>
        /// <returns></returns>
        public static T DecodeJson<T>(this string json)
        {
            if (String.IsNullOrEmpty(json)) return default(T);
            //object o = JsonConvert.DeserializeObject(json);
            //if (o.GetType() == typeof(String) || o.GetType() == typeof(string))
            //{
            //    o = JsonConvert.DeserializeObject(o.ToString());
            //}
            //object v = toObject(o);
            // System.Web.Script.Serialization.JavaScriptSerializer serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
            T d = JsonConvert.DeserializeObject<T>(json);
            return d;
        }


        /// <summary>
        /// 反序列化成对象
        /// </summary>
        /// <param name="json"></param>
        /// <returns></returns>
        public static object DecodeJson(this string json)
        {
            if (String.IsNullOrEmpty(json)) return "";
            object o = JsonConvert.DeserializeObject(json);
            if (o.GetType() == typeof(String) || o.GetType() == typeof(string))
            {
                o = JsonConvert.DeserializeObject(o.ToString());
            }
            object v = toObject(o);
            return v;
        }


        /// <summary>
        /// 将集合类转换成DataTable
        /// </summary>
        /// <param name="list">集合</param>
        /// <returns></returns>
        public static DataTable ToDataTable(IList list)
        {
            DataTable result = new DataTable();
            if (list.Count > 0)
            {
                PropertyInfo[] propertys = list[0].GetType().GetProperties();
                foreach (PropertyInfo pi in propertys)
                {
                    result.Columns.Add(pi.Name, pi.PropertyType);
                }

                for (int i = 0; i < list.Count; i++)
                {
                    ArrayList tempList = new ArrayList();
                    foreach (PropertyInfo pi in propertys)
                    {
                        object obj = pi.GetValue(list[i], null);
                        tempList.Add(obj);
                    }
                    object[] array = tempList.ToArray();
                    result.LoadDataRow(array, true);
                }
            }
            return result;
        }

        /// <summary>
        /// 将泛型集合类转换成DataTable
        /// </summary>
        /// <typeparam name="T">集合项类型</typeparam>
        /// <param name="list">集合</param>
        /// <returns>数据集(表)</returns>
        public static DataTable ToDataTable<T>(this List<T> list)
        {
            return ToDataTable<T>(list, null);
        }

        /// <summary>
        /// 将泛型集合类转换成DataTable
        /// </summary>
        /// <typeparam name="T">集合项类型</typeparam>
        /// <param name="list">集合</param>
        /// <param name="propertyName">需要返回的列的列名</param>
        /// <returns>数据集(表)</returns>
        public static DataTable ToDataTable<T>(this List<T> list, params string[] propertyName)
        {
            List<string> propertyNameList = new List<string>();
            if (propertyName != null)
                propertyNameList.AddRange(propertyName);

            DataTable result = new DataTable();
            if (list.Count > 0)
            {
                PropertyInfo[] propertys = list[0].GetType().GetProperties();
                foreach (PropertyInfo pi in propertys)
                {
                    if (propertyNameList.Count == 0)
                    {
                        result.Columns.Add(pi.Name, pi.PropertyType);
                    }
                    else
                    {
                        if (propertyNameList.Contains(pi.Name))
                            result.Columns.Add(pi.Name, pi.PropertyType);
                    }
                }

                for (int i = 0; i < list.Count; i++)
                {
                    ArrayList tempList = new ArrayList();
                    foreach (PropertyInfo pi in propertys)
                    {
                        if (propertyNameList.Count == 0)
                        {
                            object obj = pi.GetValue(list[i], null);
                            tempList.Add(obj);
                        }
                        else
                        {
                            if (propertyNameList.Contains(pi.Name))
                            {
                                object obj = pi.GetValue(list[i], null);
                                tempList.Add(obj);
                            }
                        }
                    }
                    object[] array = tempList.ToArray();
                    result.LoadDataRow(array, true);
                }
            }
            return result;
        }


        /// <summary>
        /// 弃用。。。当json 里面有;号时报错;
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="str"></param>
        /// <returns></returns>
        public static DataTable DerializeToDataTable<T>(this string str)
        {
            DataTable dt = new DataTable();
            if (str[0] == '[')//如果str的第一个字符是'['，则说明str里存放有多个model数据  
            {
                //删除最后一个']'和第一个'['，顺序不能错。不然字符串的长度就不对了。  
                //因为每个model与model之间是用 ","分隔的，所以改为用 ";"分隔  
                str = str.Remove(str.Length - 1, 1).Remove(0, 1).Replace("},{", "};{");
            }

            string[] items = str.Split(';');//用";"分隔开多条数据  
            foreach (PropertyInfo property in typeof(T).GetProperties())//反射，获得T类型的所有属性  
            {
                //创建一个新列，列名为属性名，类型为属性的类型。  
                DataColumn col = new DataColumn(property.Name, property.PropertyType);
                dt.Columns.Add(col);
            }

            //循环，一个一个的反序列化  
            for (int i = 0; i < items.Length; i++)
            {
                //创建新行  
                DataRow dr = dt.NewRow();

                //反序列化为一个T类型对象  
                T temp = DecodeJson<T>(items[i]);
                foreach (PropertyInfo property in typeof(T).GetProperties())
                {
                    //赋值  
                    dr[property.Name] = property.GetValue(temp, null);
                }
                dt.Rows.Add(dr);
            }
            return dt;
        }

        private static object toObject(object o)
        {
            if (o == null) return null;

            if (o.GetType() == typeof(string))
            {
                //判断是否符合2010-09-02T10:00:00的格式
                string s = o.ToString();
                if (s.Length == 19 && s[10] == 'T' && s[4] == '-' && s[13] == ':')
                {
                    o = System.Convert.ToDateTime(o);
                }
            }
            else if (o is JObject)
            {
                JObject jo = o as JObject;

                Hashtable h = new Hashtable();

                foreach (KeyValuePair<string, JToken> entry in jo)
                {
                    h[entry.Key] = toObject(entry.Value);
                }

                o = h;
            }
            else if (o is IList)
            {

                ArrayList list = new ArrayList();
                list.AddRange((o as IList));
                int i = 0, l = list.Count;
                for (; i < l; i++)
                {
                    list[i] = toObject(list[i]);
                }
                o = list;

            }
            else if (typeof(JValue) == o.GetType())
            {
                JValue v = (JValue)o;
                o = toObject(v.Value);
            }
            else
            {
            }
            return o;
        }
    }
}
